package com.lmm.rpc.core.cluster;


import com.lmm.rpc.core.client.NettyClient;
import com.lmm.rpc.core.client.NettyClientFactory;
import com.lmm.rpc.core.pool.TPoolObjectFactory;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.AbandonedConfig;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @title: AbstractCluster
 * @Description: TODO
 * @Author Lmm
 * @Date: 2022/9/29 15:02
 * @Version 1.0
 */
@Slf4j
public abstract class AbstractCluster<Channel> implements ICluster<io.netty.channel.Channel>{
    /**
     * 负载
     * */
    public ILoadBalancer loadBalancer;

    /**
     * 服务名(或者说接口名)
     * */
    public String serviceName;

    private NettyClient nettyClient;

    public NettyClient getNettyClient() {
        return nettyClient;
    }

    /**
     * 是否异步
     * */
    private boolean isAsync;

    /**
     * 超时时间
     * */
    private int connectTimeOut;
    private int soTimeOut;

    /**
     * 池化资源配置类
     * */
    private GenericObjectPoolConfig genericObjectPoolConfig;
    private AbandonedConfig abandonedConfig;

    /**
     * 服务拉取的池化资源缓存
     * */
    public final ConcurrentHashMap<String, GenericObjectPool<io.netty.channel.Channel>> serverPollCache = new ConcurrentHashMap();

    public AbstractCluster(ILoadBalancer loadBalancer, String serviceName, boolean async, int conTimeOut, int soTimeOut, GenericObjectPoolConfig genericObjectPoolConfig, AbandonedConfig abandonedConfig){
        this.loadBalancer = loadBalancer;
        this.serviceName = serviceName;
        this.isAsync = async;
        this.connectTimeOut = conTimeOut;
        this.soTimeOut = soTimeOut;
        this.genericObjectPoolConfig = genericObjectPoolConfig;
        this.abandonedConfig = abandonedConfig;
        this.nettyClient = NettyClientFactory.getInstance();
    }
    /**
     * 创建池
     * */
    protected GenericObjectPool<io.netty.channel.Channel> createGenericObjectPool(RemoteServerInfo remoteServer) {
        //todo 创建nettyClient
        GenericObjectPool<io.netty.channel.Channel> genericObjectPool = new GenericObjectPool( new TPoolObjectFactory(remoteServer, this.connectTimeOut, this.soTimeOut, this.isAsync ,nettyClient), this.genericObjectPoolConfig );
        genericObjectPool.setAbandonedConfig ( this.abandonedConfig );
        if (genericObjectPoolConfig.getMinIdle () == 0) {
            genericObjectPool.setMinEvictableIdleTimeMillis ( -1 );
            genericObjectPool.setSoftMinEvictableIdleTimeMillis ( -1 );
        }
        return genericObjectPool;
    }

    /**
     * 销毁池
     * */
    protected void destroyGenericObjectPool(GenericObjectPool<io.netty.channel.Channel> genericObjectPool) {
        if (genericObjectPool == null)
            return;
        genericObjectPool.close();
    }
    @Override
    public abstract void destroy();

    @Override
    public abstract RemoteServerInfo get();

    @Override
    public abstract ServerObject getObjectForRemote();
}
